package freespiritsocial.io.user.ui.activity

import android.content.Context
import android.content.Intent
import android.graphics.SurfaceTexture
import android.media.AudioManager
import android.media.MediaPlayer
import android.os.Bundle
import android.view.Surface
import android.view.TextureView
import android.view.View
import androidx.activity.result.ActivityResultLauncher
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.net.toUri
import androidx.core.view.isVisible
import com.luck.picture.lib.camera.CustomCameraType.BUTTON_STATE_BOTH
import com.luck.picture.lib.camera.CustomCameraView
import com.luck.picture.lib.camera.listener.CaptureListener
import com.luck.picture.lib.camera.listener.TypeListener
import com.luck.picture.lib.config.PictureMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.otaliastudios.cameraview.*
import freespiritsocial.io.user.R
import freespiritsocial.io.user.base.BaseActivity
import freespiritsocial.io.user.databinding.ActivityCameraBinding
import freespiritsocial.io.user.viewmodel.MainViewModel
import java.io.File

class CameraAct: BaseActivity<MainViewModel,ActivityCameraBinding>() {
    /** 文件保存位置 **/
    private var mFile: File? = null

    override fun layoutId(): Int = R.layout.activity_camera
    private var mMediaPlayer: MediaPlayer? = null
    private var recordTime = 0L

    companion object {
        fun launch(context: Context,result: ActivityResultLauncher<Intent>,type: Int) {
            result.launch(Intent(context,CameraAct::class.java).putExtra("type",type))
        }
    }

    private val surfaceTextureListener: TextureView.SurfaceTextureListener by lazy(LazyThreadSafetyMode.NONE) {
        object: TextureView.SurfaceTextureListener {
            override fun onSurfaceTextureAvailable(surface: SurfaceTexture,width: Int,height: Int) {
                startVideoPlay()
            }

            override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture,width: Int,height: Int) {}
            override fun onSurfaceTextureDestroyed(surface: SurfaceTexture): Boolean {
                return false
            }

            override fun onSurfaceTextureUpdated(surface: SurfaceTexture) {}
        }
    }

    override fun initView(savedInstanceState: Bundle?) = with(mDatabind) {
        mDatabind.camera.playSounds = false
        captureLayout.setButtonFeatures(intent.getIntExtra("type",BUTTON_STATE_BOTH))
        captureLayout.setLeftClickListener {
            finish()
        }
        camera.setLifecycleOwner(this@CameraAct)
        camera.addCameraListener(Listener())

        captureLayout.setTypeListener(object: TypeListener {
            override fun cancel() {
                onCancelMedia()
            }

            override fun confirm() {
                val mode = if (mDatabind.imagePreview.isVisible) PictureMimeType.ofImage() else PictureMimeType.ofVideo()
                val type = if (mDatabind.imagePreview.isVisible) PictureMimeType.ofJPEG() else PictureMimeType.ofMP4()
                intent.putExtra(
                    "data",LocalMedia.parseLocalMedia(
                        0,
                        mFile?.absolutePath,
                        mFile?.absolutePath,
                        mFile?.name,
                        "",
                        0,
                        mode,
                        type,
                        720,
                        1280,
                        mFile?.length() ?: 0,
                        -1,
                        System.currentTimeMillis()
                    )
                )
                setResult(RESULT_OK,intent)
                finish()
            }
        })
        captureLayout.setCaptureListener(object: CaptureListener {
            override fun takePictures() {
                mFile = File(cacheDir,"image_${System.currentTimeMillis()}.jpg")
                camera.takePicture()
            }

            override fun recordShort(time: Long) {
                mViewModel.toast.postValue("The recording time cannot not be less than 5 seconds")
                recordTime = time
                camera.stopVideo()
                clearFile()
            }

            override fun recordStart() {
                mFile = File(cacheDir,"video_${System.currentTimeMillis()}.mp4")
                val createFiles = mFile
                if (createFiles != null) {
                    camera.takeVideoSnapshot(createFiles,59000)
                }
            }

            override fun recordEnd(time: Long) {
                recordTime = time
                camera.stopVideo()
            }

            override fun recordZoom(zoom: Float) {
            }

            override fun recordError() {
                recordTime = 0L
                mViewModel.toast.postValue("Camera Error!")
                camera.stopVideo()
                clearFile()
            }
        })
        mDatabind.imageSwitch.setOnClickListener {
            camera.toggleFacing()
        }
    }

    private inner class Listener: CameraListener() {

        override fun onCameraError(exception: CameraException) {
            super.onCameraError(exception)
            finish()
        }

        override fun onPictureTaken(result: PictureResult) {
            super.onPictureTaken(result)
            if (mDatabind.camera.isTakingVideo) {
                mViewModel.toast.postValue("Captured while taking video. Size=" + result.size)
                return
            }
            mDatabind.captureLayout.setButtonCaptureEnabled(true)
            mDatabind.captureLayout.startTypeBtnAnimator()
            result.toBitmap {
                mDatabind.imagePreview.visibility = View.VISIBLE
                mDatabind.bgMask.visibility = View.VISIBLE
                mDatabind.camera.visibility = View.GONE
                mDatabind.imagePreview.setImageBitmap(it)
            }
            result.toFile(mFile!!) {
                mFile = it
            }
        }

        override fun onVideoTaken(result: VideoResult) {
            super.onVideoTaken(result)
            if (recordTime < CustomCameraView.DEFAULT_MIN_RECORD_VIDEO) {
                return
            }
            mDatabind.videoPlayPreview.visibility = View.VISIBLE
            mDatabind.bgMask.visibility = View.VISIBLE
            mDatabind.camera.visibility = View.GONE
            if (mDatabind.videoPlayPreview.isAvailable) {
                startVideoPlay()
            } else {
                mDatabind.videoPlayPreview.surfaceTextureListener = surfaceTextureListener
            }
        }

    }

    override fun onResume() {
        super.onResume()
        mDatabind.camera.open()
    }

    override fun onStart() {
        super.onStart()
        startVideoPlay()
    }

    override fun onStop() {
        super.onStop()
        stopVideoPlay()
    }

    override fun onPause() {
        super.onPause()
        mDatabind.camera.close()
    }

    override fun onDestroy() {
        super.onDestroy()
        mDatabind.camera.destroy()
    }

    fun clearFile() {
        mFile?.delete()
        mFile = null
    }

    /**
     * 取消拍摄相关
     */
    fun onCancelMedia() {
        stopVideoPlay()
        resetState()
        clearFile()
    }

    /**
     * 开始循环播放视频
     */
    private fun startVideoPlay() {
        try {
            val file = mFile ?: return
            if (mMediaPlayer == null) {
                mMediaPlayer = MediaPlayer()
            } else {
                mMediaPlayer?.reset()
            }
            mMediaPlayer?.setDataSource(this,file.toUri())
            mMediaPlayer?.setSurface(Surface(mDatabind.videoPlayPreview.surfaceTexture))
            mMediaPlayer?.setVideoScalingMode(MediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT)
            mMediaPlayer?.setAudioStreamType(AudioManager.STREAM_MUSIC)
            mMediaPlayer?.setOnVideoSizeChangedListener { mp,width,height ->
                updateVideoViewSize(
                    mMediaPlayer?.videoWidth!!.toFloat(),mMediaPlayer?.videoHeight!!.toFloat()
                )
            }
            mMediaPlayer?.setOnPreparedListener {
                if (mMediaPlayer != null) {
                    mMediaPlayer?.start()
                }
            }
            mMediaPlayer?.isLooping = true
            mMediaPlayer?.prepareAsync()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }


    private fun updateVideoViewSize(videoWidth: Float,videoHeight: Float) {
        if (videoWidth > videoHeight) {
            val videoViewParam: ConstraintLayout.LayoutParams
            val height = (videoHeight / videoWidth * mDatabind.root.width).toInt()
            videoViewParam = ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.MATCH_PARENT,height)
            videoViewParam.startToStart = ConstraintLayout.LayoutParams.PARENT_ID
            videoViewParam.endToEnd = ConstraintLayout.LayoutParams.PARENT_ID
            videoViewParam.topToTop = ConstraintLayout.LayoutParams.PARENT_ID
            videoViewParam.bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID
            mDatabind.videoPlayPreview.layoutParams = videoViewParam
        }
    }

    /**
     * 停止视频播放
     */
    private fun stopVideoPlay() {
        if (mMediaPlayer != null && mMediaPlayer!!.isPlaying) {
            mMediaPlayer?.stop()
            mMediaPlayer?.release()
            mMediaPlayer = null
        }
        mDatabind.videoPlayPreview.visibility = View.GONE
        mDatabind.bgMask.visibility = View.GONE
    }

    /**
     * 重置状态
     */
    private fun resetState() {
        mDatabind.imagePreview.visibility = View.INVISIBLE
        mDatabind.bgMask.visibility = View.GONE
        mDatabind.videoPlayPreview.visibility = View.INVISIBLE
        mDatabind.camera.visibility = View.VISIBLE
        mDatabind.captureLayout.resetCaptureLayout()
    }

}
